package main

import (
	//	"encoding/json"
	"flag"
	"fmt"
	"strconv"
	"strings"
)

type Student struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

/**
flag包实现了命令行参数的解析。
*/
func main() {
	//flagParse1()
	//flagParse2()
	flagParse3()
}

/**
定义flags有两种方式：
1）flag.Xxx()，其中Xxx可以是Int、String等；返回一个相应类型的指针，如：
var ip = flag.Int("flagname", 1234, "help message for flagname")

2）flag.XxxVar()，将flag绑定到一个变量上，如：
var flagvar int
flag.IntVar(&amp;flagvar, "flagname", 1234, "help message for flagname")
3) 自定义
*/

func flagParse1() {
	//第一个参数是命令行中参数的名字，第二个参数是默认值，第三个参数是提示用户输入的信息
	age := flag.Int64("age", 25, "请输入你的年龄") //返回一个指针
	flag.Parse()
	fmt.Println("你的年龄是:", *age)
	//运行时输入：go run main.go -age=34

	/**输入参数语法
	-flag // 只支持bool类型
	-flag=x
	-flag x // 只支持非bool类型
	*/
}

//第二种方式将输入的值绑定道一个变量上面
func flagParse2() {
	var filename string                                      //定义一个接受文件名的变量
	flag.StringVar(&filename, "file", "readme.md", "请输入文件名") //第一个参数是输入的值绑定的变量，第二个参数是命令行参数名称，第三个参数是默热文件名，第四个参数是提示用户输入信息
	flag.Parse()                                             //需要在此调用parse
	fmt.Println("你输入的文件名是:", filename)
	//运行时输入 go run main.go -file = xxx.doc
}

/**
实现flag.Value接口
type Value interface {
   String() string
   Set(string) error
}
*/

//Student实现Set方法
func (stu *Student) Set(s string) error {
	props := strings.Split(s, "#")
	name := props[0]
	age := props[1]
	/**var std Student
	jsStr := `{"name":"张三","age":2}`
	json.Unmarshal([]byte(jsStr), &std)
	fmt.Println(std)**/
	//err := json.Unmarshal([]byte(s), stu)
	v, err := strconv.ParseInt(age, 10, 32)
	if err != nil {
		fmt.Errorf("错误信息", err)
	}
	stu = &Student{Name: name, Age: int(v)}
	return err
}

//Student实现String方法
func (stu *Student) String() string {
	return "姓名:" + stu.Name + "年龄:" + strconv.Itoa(stu.Age)
}

//自定义解析参数 这种方式没有默认值，默认值就是类型的"0"值
func flagParse3() {
	stu := Student{Name: "默认姓名", Age: 23}
	flag.Var(&stu, "student", "请输入学生信息")
	flag.Parse()
	fmt.Println(stu)

	/*
		var pop percentage
		flag.Var(&pop, "pop", "popularity")
		flag.Parse()
		fmt.Println("pop:", pop)
	*/
}

type percentage float32

func (p *percentage) Set(s string) error {
	v, err := strconv.ParseFloat(s, 32)
	*p = percentage(v)
	return err
}
func (p *percentage) String() string { return fmt.Sprintf("%f", *p) }
